/**
 * @file snakeapiclient.h
 * @brief Snake游戏专用API客户端类头文件
 *
 * SnakeApiClient是专门为Snake游戏设计的API客户端，基于文档中的完整API规范实现：
 * - 游戏服务器发现和选择
 * - 游戏认证和会话管理
 * - 房间创建和管理
 * - 游戏统计和排行榜
 * - 玩家配置和设置
 */

#ifndef SNAKEAPICLIENT_H
#define SNAKEAPICLIENT_H

#include <QObject>              // Qt对象基类
#include <QJsonObject>          // JSON对象处理
#include <QJsonArray>           // JSON数组处理
#include <QDateTime>            // 时间处理
#include "apiclient.h"

/**
 * @class SnakeApiClient
 * @brief Snake游戏专用API客户端类
 *
 * 基于通用ApiClient类，提供Snake游戏专用的API调用方法。
 * 实现了完整的Snake游戏后端API接口，包括HTTP REST API和游戏会话管理。
 */
class SnakeApiClient : public QObject
{
    Q_OBJECT  // 启用Qt元对象系统

public:
    /**
     * @struct GameServerInfo
     * @brief 游戏服务器信息结构
     */
    struct GameServerInfo {
        QString serverId;               ///< 服务器唯一标识
        QString host;                   ///< 服务器主机地址
        int port = 0;                   ///< HTTP端口
        int websocketPort = 0;          ///< WebSocket端口
        QString region;                 ///< 服务器地区
        int currentPlayers = 0;         ///< 当前玩家数
        int maxPlayers = 0;             ///< 最大玩家数
        int currentRooms = 0;           ///< 当前房间数
        int maxRooms = 0;               ///< 最大房间数
        double serverLoad = 0.0;        ///< 服务器负载（0.0-1.0）
        QString status;                 ///< 服务器状态
        qint64 lastUpdated = 0;         ///< 最后更新时间
    };

    /**
     * @struct GameLoginResult
     * @brief 游戏登录结果结构
     */
    struct GameLoginResult {
        QString gameToken;              ///< 游戏会话令牌（已弃用）
        QString sessionToken;           ///< 会话令牌（用于WebSocket认证）
        QString playerId;               ///< 玩家ID
        QString sessionId;              ///< 会话ID
        QString websocketUrl;           ///< WebSocket连接URL
        GameServerInfo serverInfo;      ///< 分配的服务器信息
        QJsonObject playerProfile;      ///< 玩家档案信息
        qint64 expiresAt = 0;           ///< 令牌过期时间
    };

    /**
     * @struct RoomInfo
     * @brief 房间信息结构
     */
    struct RoomInfo {
        QString roomId;                 ///< 房间ID
        QString roomName;               ///< 房间名称
        QString creatorId;              ///< 创建者ID
        QString creatorName;            ///< 创建者名称
        int currentPlayers = 0;         ///< 当前玩家数
        int maxPlayers = 0;             ///< 最大玩家数
        QString status;                 ///< 房间状态
        int gameMode = 0;               ///< 游戏模式
        QJsonObject config;             ///< 房间配置
        qint64 createdAt = 0;           ///< 创建时间
    };

    /**
     * @struct PlayerStats
     * @brief 玩家统计信息结构
     */
    struct PlayerStats {
        QString playerId;               ///< 玩家ID
        QString username;               ///< 用户名
        int level = 0;                  ///< 等级
        qint64 totalScore = 0;          ///< 总分数
        int gamesPlayed = 0;            ///< 游戏场次
        int gamesWon = 0;               ///< 胜利场次
        double winRate = 0.0;           ///< 胜率
        int longestSnake = 0;           ///< 最长蛇身
        qint64 totalPlayTime = 0;       ///< 总游戏时间（秒）
        qint64 lastPlayed = 0;          ///< 最后游戏时间
    };

    explicit SnakeApiClient(QObject *parent = nullptr);
    ~SnakeApiClient();

    // === 初始化和配置 ===
    /**
     * @brief 设置API网关URL
     * @param gatewayUrl API网关的基础URL
     */
    void setApiGatewayUrl(const QString &gatewayUrl);

    /**
     * @brief 设置认证令牌
     * @param accessToken 访问令牌
     */
    void setAccessToken(const QString &accessToken);

    // === 服务器发现API ===
    /**
     * @brief 获取可用的游戏服务器列表
     * @param region 地区筛选（可选）
     * @param gameType 游戏类型（默认"snake"）
     */
    void getAvailableGameServers(const QString &region = QString(), 
                                const QString &gameType = "snake");

    /**
     * @brief 获取推荐的游戏服务器
     * @param region 首选地区
     */
    void getRecommendedGameServer(const QString &region = QString());

    // === 游戏认证API ===
    /**
     * @brief 游戏登录
     * @param gameType 游戏类型
     * @param preferredServerId 首选服务器ID（可选）
     * @param clientInfo 客户端信息
     */
    void gameLogin(const QString &gameType = "snake",
                   const QString &preferredServerId = QString(),
                   const QJsonObject &clientInfo = QJsonObject());

    /**
     * @brief 验证游戏令牌
     * @param gameToken 游戏令牌
     */
    void validateGameToken(const QString &gameToken);

    /**
     * @brief 刷新游戏令牌
     * @param gameToken 当前游戏令牌
     */
    void refreshGameToken(const QString &gameToken);

    // === 房间管理API ===
    /**
     * @brief 获取房间列表
     * @param status 房间状态筛选（可选）
     * @param gameMode 游戏模式筛选（可选）
     * @param limit 返回数量限制
     * @param offset 分页偏移
     */
    void getRoomList(const QString &status = QString(),
                     int gameMode = -1,
                     int limit = 50,
                     int offset = 0);

    /**
     * @brief 获取房间详细信息
     * @param roomId 房间ID
     */
    void getRoomInfo(const QString &roomId);

    /**
     * @brief 创建房间（HTTP API方式）
     * @param roomName 房间名称
     * @param config 房间配置
     */
    void createRoom(const QString &roomName, const QJsonObject &config);

    // === 游戏统计API ===
    /**
     * @brief 获取玩家统计信息
     * @param playerId 玩家ID（可选，默认当前玩家）
     */
    void getPlayerStats(const QString &playerId = QString());

    /**
     * @brief 获取排行榜
     * @param type 排行榜类型（"daily", "weekly", "monthly", "all_time"）
     * @param limit 返回数量限制
     * @param offset 分页偏移
     */
    void getLeaderboard(const QString &type = "all_time",
                        int limit = 50,
                        int offset = 0);

    /**
     * @brief 获取游戏历史记录
     * @param playerId 玩家ID（可选）
     * @param limit 返回数量限制
     * @param offset 分页偏移
     */
    void getGameHistory(const QString &playerId = QString(),
                        int limit = 20,
                        int offset = 0);

    // === 游戏配置API ===
    /**
     * @brief 获取游戏配置
     */
    void getGameConfig();

    /**
     * @brief 更新玩家配置
     * @param config 玩家配置
     */
    void updatePlayerConfig(const QJsonObject &config);

    /**
     * @brief 获取玩家配置
     */
    void getPlayerConfig();

    // === 辅助方法 ===
    /**
     * @brief 解析游戏服务器信息
     * @param serverData 服务器数据JSON
     * @return 游戏服务器信息结构
     */
    static GameServerInfo parseGameServerInfo(const QJsonObject &serverData);

    /**
     * @brief 解析游戏登录结果
     * @param loginData 登录结果JSON
     * @return 游戏登录结果结构
     */
    static GameLoginResult parseGameLoginResult(const QJsonObject &loginData);

    /**
     * @brief 解析房间信息
     * @param roomData 房间数据JSON
     * @return 房间信息结构
     */
    static RoomInfo parseRoomInfo(const QJsonObject &roomData);

    /**
     * @brief 解析玩家统计信息
     * @param statsData 统计数据JSON
     * @return 玩家统计信息结构
     */
    static PlayerStats parsePlayerStats(const QJsonObject &statsData);

signals:
    // === 服务器发现信号 ===
    /**
     * @brief 游戏服务器列表获取成功信号
     * @param servers 服务器列表
     * @param recommendedServerId 推荐服务器ID
     */
    void gameServersReceived(const QList<GameServerInfo> &servers, 
                            const QString &recommendedServerId);

    /**
     * @brief 推荐服务器获取成功信号
     * @param serverInfo 推荐服务器信息
     */
    void recommendedServerReceived(const GameServerInfo &serverInfo);

    // === 游戏认证信号 ===
    /**
     * @brief 游戏登录成功信号
     * @param loginResult 登录结果
     */
    void gameLoginSucceeded(const GameLoginResult &loginResult);

    /**
     * @brief 游戏登录失败信号
     * @param error 错误信息
     */
    void gameLoginFailed(const QString &error);

    /**
     * @brief 游戏令牌验证成功信号
     * @param playerInfo 玩家信息
     */
    void gameTokenValidated(const QJsonObject &playerInfo);

    /**
     * @brief 游戏令牌验证失败信号
     * @param error 错误信息
     */
    void gameTokenValidationFailed(const QString &error);

    // === 房间管理信号 ===
    /**
     * @brief 房间列表获取成功信号
     * @param rooms 房间列表
     * @param totalCount 总房间数
     */
    void roomListReceived(const QList<RoomInfo> &rooms, int totalCount);

    /**
     * @brief 房间信息获取成功信号
     * @param roomInfo 房间信息
     */
    void roomInfoReceived(const RoomInfo &roomInfo);

    /**
     * @brief 房间创建成功信号
     * @param roomInfo 创建的房间信息
     */
    void roomCreated(const RoomInfo &roomInfo);

    // === 统计信息信号 ===
    /**
     * @brief 玩家统计信息获取成功信号
     * @param stats 玩家统计信息
     */
    void playerStatsReceived(const PlayerStats &stats);

    /**
     * @brief 排行榜获取成功信号
     * @param leaderboard 排行榜数据
     * @param type 排行榜类型
     */
    void leaderboardReceived(const QJsonArray &leaderboard, const QString &type);

    /**
     * @brief 游戏历史记录获取成功信号
     * @param history 历史记录数据
     */
    void gameHistoryReceived(const QJsonArray &history);

    // === 配置信号 ===
    /**
     * @brief 游戏配置获取成功信号
     * @param config 游戏配置
     */
    void gameConfigReceived(const QJsonObject &config);

    /**
     * @brief 玩家配置获取成功信号
     * @param config 玩家配置
     */
    void playerConfigReceived(const QJsonObject &config);

    /**
     * @brief 玩家配置更新成功信号
     */
    void playerConfigUpdated();

    // === 错误信号 ===
    /**
     * @brief API调用失败信号
     * @param endpoint API端点
     * @param error 错误信息
     */
    void apiError(const QString &endpoint, const QString &error);

private slots:
    /**
     * @brief 处理API响应
     * @param endpoint API端点
     * @param response API响应
     */
    void onApiResponse(const QString &endpoint, const ApiClient::ApiResponse &response);

private:
    ApiClient *m_apiClient;             ///< 通用API客户端
    QString m_currentGameToken;         ///< 当前游戏令牌
    QString m_currentPlayerId;          ///< 当前玩家ID

    // === 私有辅助方法 ===
    void handleGameServersResponse(const ApiClient::ApiResponse &response);
    void handleGameLoginResponse(const ApiClient::ApiResponse &response);
    void handleRoomListResponse(const ApiClient::ApiResponse &response);
    void handlePlayerStatsResponse(const ApiClient::ApiResponse &response);
    void handleLeaderboardResponse(const ApiClient::ApiResponse &response);
    void handleGameConfigResponse(const ApiClient::ApiResponse &response);
    
    QString buildEndpoint(const QString &path) const;
    QJsonObject buildClientInfo() const;
};

#endif // SNAKEAPICLIENT_H
